#include <config.h>
#include <page_manager.h>
#include <render.h>
#include <string.h>
#include <stdlib.h>


extern void GetSelectedDir(char *strSeletedDir);
extern void GetIntervalTime(int *piIntervalSecond);

static PT_PageAction g_ptPageActionHead;

static int g_iMouseX = 0;		// 鼠标当前X坐标
static int g_iMouseY = 0;		// 鼠标当前Y坐标
static int g_iMouseBoxX;	// 鼠标交换区域当前X坐标
static int g_iMouseBoxY;	// 鼠标交换区域当前Y坐标
static T_PixelDatas g_tMouseIconPixelDatas;		// 鼠标指针图标像素数据
static T_PixelDatas g_tMouseBoxPixelDatas;		// 鼠标指针交换显示区域像素数据
static PT_PixelDatas g_ptMouseIconPixelDatas = NULL;


/**********************************************************************
 * 函数名称： GetMouseBox
 * 功能描述： 获取鼠标指针交换区域的像素数据
 * 输入参数： 无
 * 输出参数： 无
 * 返 回 值： T_PixelDatas结构体指针
 * 修改日期        版本号     修改人	      修改内容
 * -----------------------------------------------
 * 20240901	     V1.0	  Libq	      创建
 ***********************************************************************/
PT_PixelDatas GetMouseBox(void){
	return &g_tMouseBoxPixelDatas;
}


/**********************************************************************
 * 函数名称： FreeMouseBox
 * 功能描述： 舍弃鼠标指针交换区域的像素数据
 * 输入参数： 无
 * 输出参数： 无
 * 返 回 值： 无
 * 修改日期        版本号     修改人	      修改内容
 * -----------------------------------------------
 * 20240901	     V1.0	  Libq	      创建
 ***********************************************************************/
void FreeMouseBox(void){
	if (g_tMouseBoxPixelDatas.aucPixelDatas){
		free(g_tMouseBoxPixelDatas.aucPixelDatas);
		g_tMouseBoxPixelDatas.aucPixelDatas = NULL;
	}
}


/**********************************************************************
 * 函数名称： GetMouseBoxPos
 * 功能描述： 获取鼠标指针交换区域当前位置坐标
 * 输入参数： 无
 * 输出参数： iX: X坐标
 * 			 iY: Y坐标
 * 返 回 值： 无
 * 修改日期        版本号     修改人	      修改内容
 * -----------------------------------------------
 * 20240830	     V1.0	  Libq	      创建
 ***********************************************************************/
void GetMouseBoxPos(int *iX, int *iY){
	*iX = g_iMouseBoxX;
	*iY = g_iMouseBoxY;
}


/**********************************************************************
 * 函数名称： SetMouseBoxPos
 * 功能描述： 设置鼠标指针交换区域当前位置坐标
 * 输入参数： iX: X坐标
 * 			 iY: Y坐标
 * 输出参数： 无
 * 返 回 值： 无
 * 修改日期        版本号     修改人	      修改内容
 * -----------------------------------------------
 * 20240830	     V1.0	  Libq	      创建
 ***********************************************************************/
void SetMouseBoxPos(int iX, int iY){
	g_iMouseBoxX = iX;
	g_iMouseBoxY = iY;
}


/**********************************************************************
 * 函数名称： GetMouseIconPixelDatas
 * 功能描述： 获取鼠标指针图标的像素数据
 * 输入参数： 无
 * 输出参数： 无
 * 返 回 值： NULL   - 失败,没有指定的模块, 
 * 			 非NULL  - T_PixelDatas结构体指针
 * 修改日期        版本号     修改人	      修改内容
 * -----------------------------------------------
 * 20240830	     V1.0	  Libq	      创建
 ***********************************************************************/
PT_PixelDatas GetMouseIconPixelDatas(void){	// 从PNG中获取鼠标图案ARGB数据
	if (g_ptMouseIconPixelDatas)
			return g_ptMouseIconPixelDatas;
	
	T_PixelDatas tOriginIconPixelDatas;
    int iError;
    int iXres, iYres, iBpp;
    GetDispResolution(&iXres, &iYres, &iBpp);

	int iWidth = 32;
	int iHeight = 32;
	char strIconName[] = "/etc/digitpic/icons/R-C.png";	// 鼠标指针图标文件

    g_tMouseIconPixelDatas.iHeight = iHeight;
    g_tMouseIconPixelDatas.iWidth = iWidth;
    g_tMouseIconPixelDatas.iLineBytes = iWidth * iBpp / 8;
    g_tMouseIconPixelDatas.iTotalBytes = g_tMouseIconPixelDatas.iLineBytes * iHeight;
    /* 给图标分配内存 */
    g_tMouseIconPixelDatas.iBpp = iBpp;
    g_tMouseIconPixelDatas.aucPixelDatas = malloc(g_tMouseIconPixelDatas.iTotalBytes);
    if (g_tMouseIconPixelDatas.aucPixelDatas == NULL)
    {
        return NULL;
    }

    /* 从PNG文件里提取图像数据 */
    iError = GetPixelDatasFrmFile(strIconName, &tOriginIconPixelDatas);
    if (iError)
    {
        DBG_PRINTF("GetPixelDatasFrmFile %s error!\n", strIconName);
        return NULL;
    }
    PicZoom(&tOriginIconPixelDatas, &g_tMouseIconPixelDatas);
    FreePixelDatasForIcon(&tOriginIconPixelDatas);

	g_ptMouseIconPixelDatas = &g_tMouseIconPixelDatas;
	return g_ptMouseIconPixelDatas;

}


/**********************************************************************
 * 函数名称： GetMousePos
 * 功能描述： 获取鼠标指针当前位置坐标
 * 输入参数： 无
 * 输出参数： iX: X坐标
 * 			 iY: Y坐标
 * 返 回 值： 无
 * 修改日期        版本号     修改人	      修改内容
 * -----------------------------------------------
 * 20240830	     V1.0	  Libq	      创建
 ***********************************************************************/
void GetMousePos(int *iX, int *iY){
	*iX = g_iMouseX;
	*iY = g_iMouseY;
}


/**********************************************************************
 * 函数名称： SetMousePos
 * 功能描述： 设置鼠标指针当前位置坐标
 * 输入参数： iX: X坐标
 * 			 iY: Y坐标
 * 输出参数： 无
 * 返 回 值： 无
 * 修改日期        版本号     修改人	      修改内容
 * -----------------------------------------------
 * 20240830	     V1.0	  Libq	      创建
 ***********************************************************************/
void SetMousePos(int iX, int iY){
	g_iMouseX = iX;
	g_iMouseY = iY;
}


/**********************************************************************
 * 函数名称： RegisterPageAction
 * 功能描述： 注册"页面模块", "页面模块"含有页面显示的函数
 * 输入参数： ptPageAction - 一个结构体,内含"页面模块"的操作函数
 * 输出参数： 无
 * 返 回 值： 0 - 成功, 其他值 - 失败
 * 修改日期        版本号     修改人	      修改内容
 * -----------------------------------------------
 * 2013/02/08	     V1.0	  韦东山	      创建
 ***********************************************************************/
int RegisterPageAction(PT_PageAction ptPageAction)
{
	PT_PageAction ptTmp;

	if (!g_ptPageActionHead)
	{
		g_ptPageActionHead   = ptPageAction;
		ptPageAction->ptNext = NULL;
	}
	else
	{
		ptTmp = g_ptPageActionHead;
		while (ptTmp->ptNext)
		{
			ptTmp = ptTmp->ptNext;
		}
		ptTmp->ptNext	  = ptPageAction;
		ptPageAction->ptNext = NULL;
	}

	return 0;
}


/**********************************************************************
 * 函数名称： ShowPages
 * 功能描述： 显示本程序能支持的"页面模块"
 * 输入参数： 无
 * 输出参数： 无
 * 返 回 值： 无
 * 修改日期        版本号     修改人	      修改内容
 * -----------------------------------------------
 * 2013/02/08	     V1.0	  韦东山	      创建
 ***********************************************************************/
void ShowPages(void)
{
	int i = 0;
	PT_PageAction ptTmp = g_ptPageActionHead;

	while (ptTmp)
	{
		printf("%02d %s\n", i++, ptTmp->name);
		ptTmp = ptTmp->ptNext;
	}
}

/**********************************************************************
 * 函数名称： Page
 * 功能描述： 根据名字取出指定的"页面模块"
 * 输入参数： pcName - 名字
 * 输出参数： 无
 * 返 回 值： NULL   - 失败,没有指定的模块, 
 *            非NULL - "页面模块"的PT_PageAction结构体指针
 * 修改日期        版本号     修改人	      修改内容
 * -----------------------------------------------
 * 2013/02/08	     V1.0	  韦东山	      创建
 ***********************************************************************/
PT_PageAction Page(char *pcName)
{
	PT_PageAction ptTmp = g_ptPageActionHead;
	
	while (ptTmp)
	{
		if (strcmp(ptTmp->name, pcName) == 0)
		{
			return ptTmp;
		}
		ptTmp = ptTmp->ptNext;
	}
	return NULL;
}


/**********************************************************************
 * 函数名称： ID
 * 功能描述： 根据名字算出一个唯一的整数,它用来标识VideoMem中的显示数据
 * 输入参数： strName - 名字
 * 输出参数： 无
 * 返 回 值： 一个唯一的整数
 * 修改日期        版本号     修改人	      修改内容
 * -----------------------------------------------
 * 2013/02/08	     V1.0	  韦东山	      创建
 ***********************************************************************/
int ID(char *strName)
{
	return (int)(strName[0]) + (int)(strName[1]) + (int)(strName[2]) + (int)(strName[3]);
}


/**********************************************************************
 * 函数名称： GeneratePage
 * 功能描述： 从图标文件中解析出图像数据并放在指定区域,从而生成页面数据
 * 输入参数： ptPageLayout - 内含多个图标的文件名和显示区域
 *            ptVideoMem   - 在这个VideoMem里构造页面数据
 * 输出参数： 无
 * 返 回 值： 0      - 成功
 *            其他值 - 失败
 * 修改日期        版本号     修改人	      修改内容
 * -----------------------------------------------
 * 2013/02/08	     V1.0	  韦东山	      创建
 ***********************************************************************/
int GeneratePage(PT_PageLayout ptPageLayout, PT_VideoMem ptVideoMem)
{
	T_PixelDatas tOriginIconPixelDatas;
	T_PixelDatas tIconPixelDatas;
	int iError;
	PT_Layout atLayout = ptPageLayout->atLayout;
		
	/* 描画数据: VideoMem中的页面数据未生成的情况下才执行下面操作 */
	if (ptVideoMem->ePicState != PS_GENERATED)
	{
		ClearVideoMem(ptVideoMem, COLOR_BACKGROUND);

		tIconPixelDatas.iBpp          = ptPageLayout->iBpp;
        /* 分配一个临时的内存, 它用来存放缩放后的图标数据 */
		tIconPixelDatas.aucPixelDatas = malloc(ptPageLayout->iMaxTotalBytes);
		if (tIconPixelDatas.aucPixelDatas == NULL)
		{
			return -1;
		}

		while (atLayout->strIconName)
		{
            /* 取得图标文件的象素数据 */
			iError = GetPixelDatasForIcon(atLayout->strIconName, &tOriginIconPixelDatas);
			if (iError)
			{
				DBG_PRINTF("GetPixelDatasForIcon %s error!\n", atLayout->strIconName);
                free(tIconPixelDatas.aucPixelDatas);
				return -1;
			}
 			tIconPixelDatas.iHeight = atLayout->iBotRightY - atLayout->iTopLeftY + 1;
			tIconPixelDatas.iWidth  = atLayout->iBotRightX - atLayout->iTopLeftX+ 1;
			tIconPixelDatas.iLineBytes  = tIconPixelDatas.iWidth * tIconPixelDatas.iBpp / 8;
			tIconPixelDatas.iTotalBytes = tIconPixelDatas.iLineBytes * tIconPixelDatas.iHeight;

            /* 把原始的图标象素数据缩放为指定大小 */
 			PicZoom(&tOriginIconPixelDatas, &tIconPixelDatas);

            /* 把缩放后的图标数据,合并到VideoMem的指定区域 */
 			PicMerge(atLayout->iTopLeftX, atLayout->iTopLeftY, &tIconPixelDatas, &ptVideoMem->tPixelDatas);

            /* 释放原始的图标象素数据 */
 			FreePixelDatasForIcon(&tOriginIconPixelDatas);
 			atLayout++;
		}

        /* 数据上面分配的临时内存 */
		free(tIconPixelDatas.aucPixelDatas);
		ptVideoMem->ePicState = PS_GENERATED;
	}

	return 0;
}

/**********************************************************************
 * 函数名称： TimeMSBetween
 * 功能描述： 两个时间点的间隔:单位ms
 * 输入参数： tTimeStart - 起始时间点
 *            tTimeEnd   - 结束时间点
 * 输出参数： 无
 * 返 回 值： 间隔,单位ms
 * 修改日期        版本号     修改人	      修改内容
 * -----------------------------------------------
 * 2013/02/08	     V1.0	  韦东山	      创建
 ***********************************************************************/
int TimeMSBetween(struct timeval tTimeStart, struct timeval tTimeEnd)
{
	int iMS;
	iMS = (tTimeEnd.tv_sec - tTimeStart.tv_sec) * 1000 + (tTimeEnd.tv_usec - tTimeStart.tv_usec) / 1000;
	return iMS;
}

/**********************************************************************
 * 函数名称： GenericGetInputEvent
 * 功能描述： 读取输入数据,并判断它位于哪一个图标上
 * 输入参数： ptPageLayout - 内含多个图标的显示区域
 * 输出参数： ptInputEvent - 内含得到的输入数据
 * 返 回 值： -1     - 输入数据不位于任何一个图标之上
 *            其他值 - 输入数据所落在的图标(PageLayout->atLayout数组的哪一项)
 * 修改日期        版本号     修改人	      修改内容
 * -----------------------------------------------
 * 2013/02/08	     V1.0	  韦东山	      创建
 ***********************************************************************/
int GenericGetInputEvent(PT_PageLayout ptPageLayout, PT_InputEvent ptInputEvent)
{
	T_InputEvent tInputEvent;
	int iRet;
	int i = 0;
	PT_Layout atLayout = ptPageLayout->atLayout;
	
	/* 获得原始的触摸屏数据 
	 * 它是调用input_manager.c的函数，此函数会让当前线否休眠
	 * 当触摸屏线程获得数据后，会把它唤醒
	 */
	iRet = GetInputEvent(&tInputEvent);
	if (iRet)
	{
		return -1;
	}

	if (tInputEvent.iType == INPUT_TYPE_STDIN)	// 仅响应触摸点击和鼠标点击
	{
		return -1;
	}

	*ptInputEvent = tInputEvent;

	
	/* 处理鼠标事件 */
	if ((ptInputEvent->iType == INPUT_TYPE_MOUSE) && (ptInputEvent->iPressure == MOUSE_MOVE)){
		// 仅在鼠标移动时修改坐标，按下时要反转像素
		SetMousePos(ptInputEvent->iX, ptInputEvent->iY);
		SwitchRegionInDev(ptInputEvent->iX, ptInputEvent->iY, GetMouseIconPixelDatas(), GetMouseBox());
	}

	/* 处理数据 */
	/* 确定触点位于哪一个按钮上 */
	while (atLayout[i].strIconName)
	{
		if ((tInputEvent.iX >= atLayout[i].iTopLeftX) && (tInputEvent.iX <= atLayout[i].iBotRightX) && \
			 (tInputEvent.iY >= atLayout[i].iTopLeftY) && (tInputEvent.iY <= atLayout[i].iBotRightY))
		{
			/* 找到了被点中的按钮 */
			return i;
		}
		else
		{
			i++;
		}			
	}

	/* 触点没有落在按钮上 */
	return -1;
}


/**********************************************************************
 * 函数名称： GetPageCfg
 * 功能描述： 获得页面的配置参数,
 *            对于连续播放页面,它需要得到2个参数:播放哪个目录下的图片,图片之间的播放间隔
 * 输入参数： 无
 * 输出参数： ptPageCfg - 内含得到的参数
 * 返 回 值： 无
 * 修改日期        版本号     修改人	      修改内容
 * -----------------------------------------------
 * 2013/02/08	     V1.0	  韦东山	      创建
 ***********************************************************************/
void GetPageCfg(PT_PageCfg ptPageCfg)
{
    GetSelectedDir(ptPageCfg->strSeletedDir);
    GetIntervalTime(&ptPageCfg->iIntervalSecond);
}

/**********************************************************************
 * 函数名称： PagesInit
 * 功能描述： 调用各个"页面模块"的初始化函数,就是注册它们
 * 输入参数： 无
 * 输出参数： 无
 * 返 回 值： 0 - 成功, 其他值 - 失败
 * 修改日期        版本号     修改人	      修改内容
 * -----------------------------------------------
 * 2013/02/08	     V1.0	  韦东山	      创建
 ***********************************************************************/
int PagesInit(void)
{
	int iError;

	iError  = MainPageInit();
	iError |= SettingPageInit();
	iError |= IntervalPageInit();
	iError |= BrowsePageInit();
    iError |= AutoPageInit();
    iError |= ManualPageInit();		
    iError |= ReadingPageInit();		
    iError |= VideoPageInit();		
	return iError;
}


